package com.feicheng.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.feicheng.common.constant.Constant;
import com.feicheng.common.exception.SystemException;
import com.feicheng.common.result.ResultInfo;
import com.feicheng.persistence.entity.*;
import com.feicheng.persistence.model.Cmd;
import com.feicheng.persistence.service.*;
import com.feicheng.service.BaseService;
import com.feicheng.service.IFCheckCodeService;
import com.feicheng.service.IFClientService;
import com.feicheng.service.IFOrderService;
import com.feicheng.service.IFStoreService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;

@Service
@Slf4j
public class FCheckCodeServiceImpl extends BaseService implements IFCheckCodeService {

    @Autowired
    IAccountService iAccountService;

    @Autowired
    IStoreAccessService iStoreAccessService;

    @Autowired
    IStoreClientService iStoreClientService;

    @Autowired
    IFClientService ifClientService;

    @Autowired
    IClientService iClientService;

    @Autowired
    IAccessService iAccessService;

    @Autowired
    IFStoreService ifStoreService;

    @Autowired
    IFOrderService ifOrderService;

    @Autowired
    IOrderService iOrderService;

    @Autowired
    IStoreService iStoreService;

    @Autowired
    IStoreUserRoleService iStoreUserRoleService;

    @Autowired
    IStoreUserService iStoreUserService;

    @Autowired
    IStoreUserInfoService iStoreUserInfoService;

    /*
     储存命令的全局变量
     key：取当前时间为命令编号用于区分命令
     value：区域id，授权key，设备id(这三个用于区分门禁)，命令编号
     */
    Map<Long, Cmd> cmdMap = new HashMap<>();

    @Override
    public String ifOpenDor(JSONObject qCedeAccessValByCut) {

        /*
         构建两个对象，当为合法时返回开门的对象OpenDor，不合法时返回拒绝开门对象CloseDor
         */
        //生成开门对象
        JSONObject openDor = new JSONObject();
        openDor.put(Constant.MODEL_NAME.QCODEACCESSVAL.UID, qCedeAccessValByCut.get(Constant.MODEL_NAME.QCODEACCESSVAL.UID));
        openDor.put(Constant.MODEL_NAME.QCODEACCESSVAL.STATUS, 1);
        //生成不开门对象
        JSONObject closeDor = new JSONObject();
        closeDor.put(Constant.ENTITY.ACCESS.U_ID, qCedeAccessValByCut.get(Constant.MODEL_NAME.QCODEACCESSVAL.UID));
        closeDor.put(Constant.MODEL_NAME.QCODEACCESSVAL.STATUS, 0);

        //取得门禁值的区域id
        Integer viewValByAcc = qCedeAccessValByCut.getInteger(Constant.MODEL_NAME.QCODEACCESSVAL.VIEWID);
        //取得门禁值中的uid
        String uidValByAcc = qCedeAccessValByCut.getString(Constant.MODEL_NAME.QCODEACCESSVAL.UID);

        //取得门禁值中的ukey
        String uKeyValByAcc = qCedeAccessValByCut.getString(Constant.MODEL_NAME.QCODEACCESSVAL.UKEY);

        //取得二维码值对象
        String qCodeStr = qCedeAccessValByCut.getString(Constant.MODEL_NAME.QCODEACCESSVAL.CODEVAL);


        //将二维码值按，切割
        String[] qCodeStrS = qCodeStr.split(Constant.MODEL_NAME.QCODEVAL.COMMA);
        //判断二维码信息
        if(4 != qCodeStrS.length){
            // TODO: 2021/12/16 二维码有误，请联系管理员！
            return JSONObject.toJSONString(closeDor);
        }

        //取得clientid并转成int
        int clientId = Integer.parseInt(qCodeStrS[0]);
        //取的storeid并转成int
        int storeId = Integer.parseInt(qCodeStrS[1]);

        //取得二维码结束时间并转成时间格式
        String edByAcc = qCodeStrS[3].replace(Constant.MODEL_NAME.QCODEVAL.TIMEOLD, Constant.MODEL_NAME.QCODEVAL.TIMENEW);
        SimpleDateFormat formatter = new SimpleDateFormat(Constant.MODEL_NAME.QCODEVAL.TIME);
        ParsePosition pos = new ParsePosition(0);
        Date strtodate = formatter.parse(edByAcc, pos);
        //判断二维码时间是否有效
        //获取结束时间并转成
        Date date = new Date();
        //比较扫码时间是否在二维码有效期内
        int res = strtodate.compareTo(date);
        if ( res < 0 ){
            // TODO: 2021/12/16 二维码过期，请重新生成二维码！
            return JSONObject.toJSONString(closeDor);
        }

        //构建条件构造器
        QueryWrapper<Client> clientQueryWrapper = new QueryWrapper<>();
        //把clientid放入构造器
        clientQueryWrapper.eq(Constant.ENTITY.CLIENT.CLIENT_ID,clientId);
        //执行查询取得client对象
        Client client = iClientService.getOne(clientQueryWrapper);
        //判断客户对象是否存在
        if (null == client){
            return JSONObject.toJSONString(closeDor);
        }
        //未支付订单
        QueryWrapper<Order> orderWrapper = new QueryWrapper<>();
        orderWrapper.eq(Constant.ENTITY.ORDER.CLIENT_ID, clientId);
        orderWrapper.eq(Constant.ENTITY.ORDER.STATU, Constant.MODEL_NAME.Order.UNPAY);
        List<Order> orderList = iOrderService.list(orderWrapper);
        if(null != orderList && 0 < orderList.size()){
            // TODO: 2021/12/16 未支付订单
            return JSONObject.toJSONString(closeDor);
        }

        //判断设备返回的数据
        if (null == viewValByAcc
                || null == uidValByAcc
                || null == uKeyValByAcc){
            // TODO: 2021/12/16 设备返回的数据有误，请联系管理员！
            return JSONObject.toJSONString(closeDor);
        }

        //判断门店是否一致
        if (storeId != viewValByAcc){
            // TODO: 2021/12/16 您不是本店客户，请确认门店进行锻炼！
            return JSONObject.toJSONString(closeDor);
        }

        //构建条件构造器
        QueryWrapper<Account> accountQueryWrapper = new QueryWrapper<>();
        //判断是否支付押金
        accountQueryWrapper.eq(Constant.ENTITY.ACCOUNT.CLIENT_ID, clientId);
        accountQueryWrapper.gt(Constant.ENTITY.ACCOUNT.DEPOSIT_AMOUNT,0);
        int count = iAccountService.count(accountQueryWrapper);
        if (count <= 0){
            // TODO: 2021/12/16 您还未支付押金，请先支付后生成二维码！
            return JSONObject.toJSONString(closeDor);
        }

        QueryWrapper<Access> accessQueryWrapper = new QueryWrapper<>();
        //把设备返回值中的uid放入查询条件
        accessQueryWrapper.eq(Constant.ENTITY.ACCESS.U_ID,uidValByAcc);

        //把ukey放入查询条件
        accessQueryWrapper.eq(Constant.ENTITY.ACCESS.U_KEY,uKeyValByAcc);
        //执行查询得到门禁对象
        accessQueryWrapper.eq(Constant.ENTITY.ACCESS.D_FLG, 0);
        Access ifAccess = iAccessService.getOne(accessQueryWrapper);
        //查不到门禁
        if(null == ifAccess){
            // TODO: 没有对应的门禁设备
            return JSONObject.toJSONString(closeDor);
        }

        //取得门禁对象中的accessid
        Integer accessIdByAcc = ifAccess.getAccessId();

        //根据门禁id查门店-门禁对象
        QueryWrapper<StoreAccess> storeAccessQueryWrapper = new QueryWrapper<>();
        storeAccessQueryWrapper.eq(Constant.ENTITY.STORE_ACCESS.ACCESS_ID,accessIdByAcc);
        StoreAccess storeAccessServiceById = iStoreAccessService.getOne(storeAccessQueryWrapper);
        //查询进出门信息
        Boolean ioFlg = storeAccessServiceById.getIoFlg();

        //生成扫码记录对象
        AccessRecord accessRecord = new AccessRecord();
        accessRecord.setAccessId(accessIdByAcc);
        accessRecord.setClientId(clientId);
        accessRecord.setStoreId(storeId);
        accessRecord.setCt(LocalDateTime.now());


        //根据clientid找order中的st订单
        QueryWrapper<Order> orderQueryWrapper = new QueryWrapper<>();
        orderQueryWrapper.eq(Constant.ENTITY.ORDER.CLIENT_ID, clientId);
        orderQueryWrapper.eq(Constant.ENTITY.ORDER.STATU, Constant.MODEL_NAME.Order.ST);
        orderQueryWrapper.eq(Constant.ENTITY.ORDER.D_FLG, 0);
        Order orderBySt = iOrderService.getOne(orderQueryWrapper);
        //生成禁扫码记录
        ifStoreService.newAccessRecord(accessRecord);
        //根据进出门状态判断调订单接口
        if (!ioFlg){
            //出门
            if (null == orderBySt){
                // 出门重复扫码
                return JSONObject.toJSONString(closeDor);
            }

            //调结算接口
            ifOrderService.consumeOrder(orderBySt.getOrderId());
        } else {
            //进门
            //有已开始订单
            if(null != orderBySt){
                return JSONObject.toJSONString(openDor);
            } else {
                //生成订单
                //把生成订单的参数放到order对象中
                Order order = new Order();
                order.setClientId(clientId);
                order.setStoreId(storeId);
                order.setClientName(iClientService.getById(clientId).getClientName());
                order.setStoreName(iStoreService.getById(storeId).getName());
                //声明传入订单接口的参数
                JSONObject orderJsonIn = new JSONObject();
                orderJsonIn.put(Constant.ENTITY.ORDER.TABLE, order);
                // 调生成订单接口   生成订单
                ifOrderService.createOrder(orderJsonIn);
            }
        }
        return JSONObject.toJSONString(openDor);
    }

    /**
     * 清理失效命令
     */
    public void cleanCmd() {
        if(null != cmdMap){
            for (Long cmdTime : cmdMap.keySet()) {
                if (System.currentTimeMillis() - cmdTime > 600000) {
                    cmdMap.remove(cmdTime);
                }
            }
        }
    }

    @Override
    public ResultInfo newCmdToMap(Integer accessId, Integer CmdCode) {
        Access access = iAccessService.getById(accessId);
        QueryWrapper<StoreAccess> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(Constant.ENTITY.STORE_ACCESS.ACCESS_ID, access.getAccessId());
        String storeId = iStoreAccessService.getOne(queryWrapper).getStoreId().toString();
        Cmd cmd = new Cmd();
        cmd.setViewId(storeId);
        cmd.setUId(access.getUId());
        cmd.setUKey(access.getUKey());
        cmd.setCmdCode(CmdCode);
        cmdMap.put(System.currentTimeMillis(), cmd);
        return ResultInfo.success();
    }
    @Override
    public ResultInfo newCmdToMapWX(String password, Integer accessId, Integer storeId, Integer CmdCode) {
        //得到门店userid
        QueryWrapper<StoreUserInfo> storeUserInfoQueryWrapper = new QueryWrapper<>();
        storeUserInfoQueryWrapper.eq(Constant.ENTITY.STORE_USER_INFO.STORE_ID, storeId);
        List<StoreUserInfo> storeUserInfos = iStoreUserInfoService.list(storeUserInfoQueryWrapper);
        List<Integer> storeUserIds = new ArrayList<>();
        for (StoreUserInfo storeUserInfo : storeUserInfos) {
            storeUserIds.add(storeUserInfo.getUserId());
        }
        //得到门店管理员userid
        QueryWrapper<StoreUserRole> userRoleQueryWrapper = new QueryWrapper<>();
        userRoleQueryWrapper.eq(Constant.ENTITY.USER_ROLE.ROLE_ID, 1);
        userRoleQueryWrapper.in(Constant.ENTITY.USER_ROLE.USER_ID, storeUserIds);
        List<StoreUserRole> userRoles = iStoreUserRoleService.list(userRoleQueryWrapper);
        if(0 < userRoles.size()){
            List<Integer> userIds = new ArrayList<>();
            for (UserRole userRole : userRoles) {
                userIds.add(userRole.getUserId());
            }

            List<StoreUser> users = iStoreUserService.listByIds(userIds);
            for (User user : users) {
                if (password.equals(user.getPassword())) {
                    return this.newCmdToMap(accessId, CmdCode);
                }
            }
        }
        throw new SystemException("密码错误");
    }


    @Override
    public String accessGetCmd(String ViewId, String UID, String UKey) {
        JSONObject noCmdJSON = new JSONObject();
        noCmdJSON.put(Constant.MODEL_NAME.CMD.CMD_ID, 0);
        noCmdJSON.put(Constant.MODEL_NAME.CMD.CMD_CODE, 0);
        JSONObject haveCmdJSON = new JSONObject();
        for(Map.Entry<Long, Cmd> cmd : cmdMap.entrySet()){
            if(
                    cmd.getValue().getViewId().equals(ViewId) &&
                    cmd.getValue().getUId().equals(UID)  &&
                    cmd.getValue().getUKey().equals(UKey)
            ){
                haveCmdJSON.put(Constant.MODEL_NAME.CMD.CMD_ID, cmd.getKey().toString());
                haveCmdJSON.put(Constant.MODEL_NAME.CMD.CMD_CODE, cmd.getValue().getCmdCode());
                return haveCmdJSON.toJSONString();
            }
        }
        return noCmdJSON.toJSONString();
    }

    @Override
    public String removeCmd(Long cmdId, Integer CmdStatus) {
        JSONObject re = new JSONObject();
        if(1 == CmdStatus) {
            cmdMap.remove(cmdId);
        }
        re.put(Constant.MODEL_NAME.CMD.CMD_STATUS, 1);
        return re.toJSONString();
    }
}
